package cmd

import (
	"context"
	"fmt"
	"github.com/goflyfox/gtoken/gtoken"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/net/ghttp"
	"github.com/gogf/gf/v2/net/goai"
	"github.com/gogf/gf/v2/os/gcmd"
	"github.com/gogf/gf/v2/text/gstr"
	"ticket/api/order"
	"ticket/api/purchase"
	"ticket/api/user"
	_ "ticket/captcha/captcha"
	"ticket/captcha/router"
	"ticket/doc"
)

// 定义不需要进行 Token 验证的路由列表
var authExcludePaths = g.SliceStr{
	"/api/user",
	"/api/logout",
	"/api/v1/back/captcha/get",
}

// 定义密钥
var encryptKey = []byte("87d6rasd89sy8tdyfuaghsfiu897y8ty")

var (
	Main = gcmd.Command{
		Name:  "main",
		Usage: "main",
		Brief: "start http server",
		Func: func(ctx context.Context, parser *gcmd.Parser) (err error) {
			server := g.Server()
			// 关闭打印的路由表
			server.SetDumpRouterMap(false)
			// 初始化Swagger
			InitSwagger(server, ctx)
			// 初始化GToken
			InitGToken()
			// 初始化API
			InitAPI(server)
			server.Run()
			return nil
		},
	}
)

// 初始化API
func InitAPI(server *ghttp.Server) {
	// 注册业务代码的路由信息
	server.Group("/api/v1/back", func(group *ghttp.RouterGroup) {
		group.Middleware(ghttp.MiddlewareHandlerResponse)
		// 注册验证码SPI
		router.InitCaptchaApiRouter(group)
		// 用户相关API
		user.InitUserRouter(group)
		// 注册购票页面的API
		purchase.InitUserAgentApiRouter(group)
		// 注册订单页面的API
		order.InitUserOrderApiRouter(group)
	})
}

// 初始化GToken
func InitGToken() {
	// 设置 Token 相关的信息
	gfToken := &gtoken.GfToken{
		CacheMode:        2,                       // 使用 Redis 存储 Token 信息
		EncryptKey:       encryptKey,              // 加密的密钥
		LoginPath:        "/api/login",            // 登录的路径
		LogoutPath:       "/api/logout",           // 登出的路径(不需要写内部函数实现)
		AuthExcludePaths: authExcludePaths,        // 排除不需要拦截的路径
		AuthPaths:        g.SliceStr{"/api/v1/*"}, // 拦截/api/v1/下的所有路径
		LoginBeforeFunc:  user.LoginFunc,          // 登陆的函数
		LoginAfterFunc:   user.LoginAfter,         // 登陆完成调用的函数
		Timeout:          3600000,                 // 有效期一小时
		AuthFailMsg:      "请先登录",                  // 提示信息
	}
	// 启动 Token 中间件
	gfToken.Start()
}

// 初始化Swagger
func InitSwagger(server *ghttp.Server, ctx context.Context) {
	server.AddStaticPath("/doc", "resources/public/doc")
	server.BindHookHandler("/swagger/*", ghttp.HookBeforeServe, func(r *ghttp.Request) {
		content := gstr.ReplaceByMap(doc.SwaggerUITemplate, map[string]string{
			`{SwaggerUIDocUrl}`:             g.Cfg().MustGet(ctx, "server.openapiPath").String(),
			`{SwaggerUIDocNamePlaceHolder}`: gstr.TrimRight(fmt.Sprintf(`//%s`, r.Host)),
		})
		r.Response.Write(content)
		r.ExitAll()
	})
	openapi := server.GetOpenApi()
	openapi.Config.CommonResponse = ghttp.DefaultHandlerResponse{}
	openapi.Config.CommonResponseDataField = `Data`
	openapi.Info = goai.Info{
		Title:       doc.OpenAPITitle,
		Description: doc.OpenAPIDescription,
		Contact: &goai.Contact{
			Name: doc.OpenAPIContactName,
			URL:  doc.OpenAPIContactUrl,
		},
	}
}
